#ifndef _0A4EB75C_F5B5_4832_BFC9_A55E6B0BBEEF_DOT
#define _0A4EB75C_F5B5_4832_BFC9_A55E6B0BBEEF_DOT
#include <cstdio>
#include <cstdarg>

using namespace std;

class visualize
{
private:
    enum tokens
    {
        eFROM = 0,
        eTO = 1,
        eEND
    };
private:
    FILE* _fileHd;
    const char* _name;
    unsigned int _size;
    bool _directed;

public:
    visualize(const char* name) : _name(name), _fileHd(NULL), _size(0)
    {
    }

    ~visualize()
    {
        if(_fileHd)
        {
            fclose(_fileHd);
        }
    }

    bool init(const char* graphName = "default", const char* type = "graph")
    {
        if(_name && strlen(_name))
        {
            _fileHd = fopen(_name, "w");
        }

        if(!_fileHd)
        {
            return false;
        }

        if(_stricmp(type, "digraph "))
        {
            _directed = true;
        }
        else
            _directed = false;
        fprintf(_fileHd, "%s %s{\n",type, graphName);
        return true;
    }

    bool commit()
    {
        if(_fileHd)
        {
            fprintf(_fileHd, "}\n");
            fflush(_fileHd);
            _fileHd = NULL;
            return true;
        }

        return false;
    }

    int gwrite(const char* format, ...)
    {
        va_list vl;
        va_start(vl, format);
        int ret = -1;
        char* fromNode = NULL;
        char* toNode = NULL;
        tokens nextTok = eEND;
        _size = strlen(format);
        char* arrow = NULL;
        
        if(_directed)
            arrow = "->";
        else
            arrow = "--";

        for(int i = 0 ; i < _size; i++)
        {
            nextTok = getNextTokenStr(format, i, &i);
            switch(nextTok)
            {
            case eFROM:
                fprintf(_fileHd, "%s", va_arg(vl, char*));
            case eTO:
                fprintf(_fileHd, "%s%s", arrow, va_arg(vl, char*));
            }
        }

        va_end(vl);
        return ret;
    }

    /*template < int N >
    tokens getNextTokenStr(char (&str)[N], int* end)
    {
        return eEND;
    }*/
private:
    tokens getNextTokenStr(const char* str, const int start, int* end)
    {
        for(int i = start; i < _size; i++)
        {
            eatSpaces(str, i);
            if('*' == str[i++])
            {
                switch(str[i])
                {
                case 'f':
                    if('r' == str[++i])
                    {
                        *end = i;
                        return eFROM;
                    }
                case 't':
                    if('o' == str[++i])
                    {
                        *end = i;
                        return eTO;
                    }
                default:
                    *end = -1;
                    return eEND;
                }
            }
        }
        
        return eEND;
    }

    int eatSpaces(const char* str, int len)
    {
        while(' ' == str[len])
            len++;//NULL statement
        return len;
    }

};

#endif //_0A4EB75C_F5B5_4832_BFC9_A55E6B0BBEEF_DOT

